//------------------------------------------------------------------------------
//!	@file	ProcGamma.c
//!	@brief
//!		Calculate LUTs
//!
//!	@Description
//!		Calculation LUT algorithms
//!
//!
//!	Originally Developed: July, 1997 to October, 1999
//!
//!	$Id: ProcGamma.c 158 2013-03-03 07:00:15Z ac.verbeck@gmail.com $
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//	Copyright and Disclaimer Notice
//
//	Copyright (c) 2013 A.C. Verbeck
//
//	This file is part of CreateLUT: A LUT creation library.
//
//	CreateLUT is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	CreateLUT is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with CreateLUT.  If not, see <http://www.gnu.org/licenses/>.
//
//------------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <math.h>

#include <stdint.h>
#include <stdbool.h>

#include "ProcGamma.h"
#include "SysParam.h"

//
//	File local variables
//
static FILE	*OutFile;

//
//	Local functions
//
static void Gamma_ProcessLut(void);
static void Gamma_BuildLut(uint8_t* OutLut, double Gain, double Gamma);
static void Gamma_WriteLut(uint8_t* tab);


//
//	Name:
//		Gamma_Execute
//
//	Description:
//		Loads the raw color data into an array for further processing.
//		Does some error checking where possible.
//		Exits if error tests fail.
//
//	Parameters:
//		char*	InFile:		Input file
//		double*	r:			Red data array
//		double*	g:			Green data array
//		double*	b:			Blue data array
//
//	Returns:
//		(No direct return)
//		Indirect: The r,g, and b arrays are filled.
//
void Gamma_Execute(void)
{
	extern char OutFileName[];

//
//	Open the output file & debug file
//
	OutFile = fopen(OutFileName,"wb");
	if (OutFile == NULL) {
		printf("File open error: %s\n",OutFileName);
		exit(1);
	}

//
//	Process the EO curves
//
	printf("Processing red data:"); 			//	Process Red
	Gamma_ProcessLut();
	printf("Processing green data:");			//	Process Green
	Gamma_ProcessLut();
	printf("Processing blue data:");			//	Process Blue
	Gamma_ProcessLut();
	printf("Processing complete.\n");
	fclose(OutFile);
}


//
//	Name:
//		Gamma_ProcessLut
//
//	Description:
//
//	Parameters:
//		uint8_t*	InputFileName:	Input file name (color table)
//
//	Returns:
//		(None)
//
static void Gamma_ProcessLut(void)
{
	double	GammaIdx,GammaInc;
	double	GainIdx,GainInc;
	uint8_t	OutLutTable[CURVE_SZ_08BIT];

	int32_t	i,j;

	extern double	StartGamma;
	extern double	EndGamma;
	extern int32_t	LutGammaCt;

	extern double	StartGain;
	extern double	EndGain;
	extern int32_t	LutGainCt;


//
//	Process the file
//
	GainInc  = (EndGain-StartGain)/(double)(LutGainCt-1);
	GammaInc = (EndGamma-StartGamma)/(double)(LutGammaCt-1);

	for (GainIdx=StartGain,i=0; i<LutGainCt; GainIdx+=GainInc,i++) {
		for (GammaIdx=StartGamma,j=0; j<LutGammaCt; GammaIdx+=GammaInc,j++) {
			memset(OutLutTable, 0, CURVE_SZ_08BIT);
			Gamma_BuildLut(OutLutTable, GainIdx, GammaIdx);
			Gamma_WriteLut(OutLutTable);
		}
		printf(".");
	}
	printf("\n");
}


//
//	Name:
//		Gamma_BuildLut
//
//	Description:
//		Generates a single LUT based on the following:
//		-- A normaized LUT
//		-- Gain
//		-- Gamma
//
//	Parameters:
//		uint8_t*	OutLut:		Output LUT (256 entries)
//		double*			NormLut:	Input Normalized LUT (256 entries)
//		double			Gain:		Gain to be applied to this LUT
//		double			Gamma:		Gamma to be applied to this LUT
//
//	Returns:
//		(No direct return)
//		Indirect: The OutLut[TableSz] array is filled.
//
static void Gamma_BuildLut(uint8_t* OutLut, double Gain, double Gamma)
{
	double	tIdx,tInc;
	double	dVal;
	int32_t	i;

//
//	Pre LUT production
//
	tInc = (double)1/(double)(CURVE_SZ_08BIT-1);

//
//	LUT production
//
	for (i=0,tIdx=0.0; i<CURVE_SZ_08BIT; i++,tIdx+=tInc) {
		dVal = pow(tIdx,Gamma)*Gain;
		OutLut[i] = (uint8_t)(dVal*255.0);
	}
}


//
//	Name:
//		Gamma_WriteLut
//
//	Description:
//		Writes a raw binary LUT table to a file.
//		This file will be converted to S-Records by the
//		SDS down program.
//
//	Parameters:
//		uint8_t*	tab:		Binary LUT table to be written.
//
//	Returns:
//		(No direct return)
//		Indirect: The tab[TABLE_SZ] array is written to the output file.
//
static void Gamma_WriteLut(uint8_t* tab)
{
	fwrite(tab, 1, CURVE_SZ_08BIT, OutFile);
}

//
//	End: ProcGamma.c
//
